'''
实现一个用于演示的数据库系统，将数据存在内存里面。

其它模块引入此模块应该仅引入`getDatabase`函数。
'''

import html

from abc import ABCMeta, abstractmethod
from typing import Any, Iterable
from itertools import islice

from .database import COL_NAMES


TEMPLATE = '''
<!DOCTYPE html>
<html>

<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width">
<title>后端demo</title>
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.1/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-4bw+/aepP/YC94hEpVNVgiZdgIC5+VKNBQNGCHeKRQN+PtmoHDEXuppvnDJzQIu9" crossorigin="anonymous">
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.1/dist/js/bootstrap.bundle.min.js" integrity="sha384-HwwvtgBNo3bZJJLYd8oVXjrBZt8cqVSpeBNS5n7C8IVInixGAoxmnlMuBnhbgrkm" crossorigin="anonymous"></script>
</head>

<body>
<div class="container">
<table class="table table-hover">
<thead><tr>
    %s
</tr></thead>
<tbody>
    {}
</tbody>
</table>
</div>
</body>
</html>
''' % '\n'.join(f'<th>{html.escape(name)}</th>' for name in COL_NAMES)

def showDatas(datas: Iterable[tuple[str, ...]], limit = 100):
    return TEMPLATE.format('\n'.join(
        '<tr>{}</tr>'.format(
            '\n'.join(f'<td>{html.escape(str(item))}</td>' for item in row)
        ) for row in islice(datas, limit)
    ))


class Database(metaclass = ABCMeta):

    @abstractmethod 
    def insert(self, *a, **w): ...
    @abstractmethod
    def getDatas(self) -> Iterable[tuple[int, int]]: ...
    @abstractmethod
    def erase(self, *a, **w): ...
    @abstractmethod
    def get(self, *a, **w) -> Any: ...
    
    def show(self):
        return showDatas(self.getDatas())


class DictDatabase(Database):

    def __init__(self):
        self.datas: dict[str, str] = dict()

    def insert(self, stuId: str, bandId: str):
        self.datas[stuId] = bandId

    def erase(self, stuId: str):
        return self.datas.pop(stuId, None)

    def get(self, stdId: str):
        return self.datas.get(stdId)
    

_dataBase = None
def getDatabase():
    global _dataBase
    if not _dataBase:
        _dataBase = DictDatabase()
    return _dataBase
